package com.common;

import com.common.file.ByteUploadResource;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.util.*;

/**
 * Created by lzb on 2017/12/18.
 */
public class ReqObject {

    String url;
    HttpHeaders heads=new HttpHeaders();
    MultiValueMap<String, Object> params = new LinkedMultiValueMap<String, Object>();
    private RestTemplate restTemplate;
    public ReqObject(String url){
        this.url=url;
    }
    public ReqObject(String url, HttpServletRequest request){

        try {
            String mimeType=request.getHeader("Content-Type");
            if(mimeType != null && mimeType.startsWith("multipart/form-data")){//上传文件请求,请用zuul的过滤透传URL,否则文件名乱码
                List<Part> formdata= (List<Part>) request.getParts();
                formdata.forEach(p -> {
                    try{
                        if(!UtilTools.isNullOrBlank(p.getSubmittedFileName())) {//文件
                            ByteUploadResource bus = new ByteUploadResource(p.getInputStream(), java.net.URLEncoder.encode(p.getSubmittedFileName(), "UTF-8"));
                            addParam(p.getName(),bus);
                        }else{//表单字段
                            addParam(p.getName(),request.getParameter(p.getName()));
                        }
                    }catch (Exception e){throw new RuntimeException(e);}
                });
            }else{//正常请求
                Map<String, String[]> map = request.getParameterMap();
                Iterator<String> it = map.keySet().iterator();
                while (it.hasNext()) {
                    String key = it.next();
                    params.put(key, Arrays.asList(map.get(key)));
                }
            }
            //把头也带上
            Enumeration<String> et=request.getHeaderNames();
            while(et.hasMoreElements()){
                String key=et.nextElement();
                if("cookie".equalsIgnoreCase(key))continue;
                Enumeration<String> es=request.getHeaders(key);
                while(es.hasMoreElements())addHead(key,es.nextElement());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        this.url=url;
    }

    public ReqObject addParam(String key, Object value){
        params.add(key,value);
        return this;
    }

    public ReqObject addHead(String key, String value){
        heads.add(key,value);
        return this;
    }

    /**
     * 异步请求不支持TCC事务
     * @param glzz
     * @param callbackFunc
     * @param <T>
     */
    public <T> void syncdeal(ParameterizedTypeReference<T> glzz,ListenableFutureCallback<ResponseEntity<T>> callbackFunc){
        HttpEntity<MultiValueMap> request  = new HttpEntity<MultiValueMap>(params,heads);
        ListenableFuture<ResponseEntity<T>> future = Constant.ctx.getBean(AsyncRestTemplate.class).exchange(url, HttpMethod.POST, request,glzz);
        future.addCallback(callbackFunc);
    }

    public <T> void syncget(ParameterizedTypeReference<T> glzz,ListenableFutureCallback<ResponseEntity<T>> callbackFunc){
        HttpEntity<MultiValueMap> request  = new HttpEntity<MultiValueMap>(params,heads);
        ListenableFuture<ResponseEntity<T>> future = Constant.ctx.getBean(AsyncRestTemplate.class).exchange(url, HttpMethod.GET, request,glzz);
        future.addCallback(callbackFunc);
    }

    public <T> T get(Class<T> glzz){
        HttpEntity<MultiValueMap> request  = new HttpEntity<MultiValueMap>(params,heads);
        if(this.restTemplate==null)this.restTemplate=Constant.ctx.getBean(RestTemplate.class);
        return this.restTemplate.getForObject(url,glzz);
    }

    public <T> T deal(Class<T> glzz){
        HttpEntity<MultiValueMap> request  = new HttpEntity<MultiValueMap>(params,heads);
        if(this.restTemplate==null)this.restTemplate=Constant.ctx.getBean(RestTemplate.class);
        return this.restTemplate.postForObject(url,request,glzz);
    }

    public ReqObject setTemplate(RestTemplate t){
        this.restTemplate=t;
        return this;
    }

    public <T> ResponseEntity<T> exchange_get(ParameterizedTypeReference<T> typeRef){
//        ParameterizedTypeReference<T> typeRef = new ParameterizedTypeReference<T>() {};
        HttpEntity<MultiValueMap> request  = new HttpEntity<MultiValueMap>(params,heads);
        return Constant.ctx.getBean(RestTemplate.class).exchange(
                url,
                HttpMethod.GET,
                request,
                typeRef);
    }

    public <T> ResponseEntity<T> exchange(ParameterizedTypeReference<T> typeRef){
//        ParameterizedTypeReference<T> typeRef = new ParameterizedTypeReference<T>() {};
        HttpEntity<MultiValueMap> request  = new HttpEntity<MultiValueMap>(params,heads);
        return Constant.ctx.getBean(RestTemplate.class).exchange(
                url,
                HttpMethod.POST,
                request,
                typeRef);
    }
}